Skip to content

docs(spec): describe the form-section collapse pair on both keys - #19736

Merged
os-support-ai merged 3 commits into
mainfrom
claude/issue-19311-form-section-collapse-describes
Sep 22, 2026
Merged

os-support-ai merged 3 commits into
mainfrom
claude/issue-19311-form-section-collapse-describes

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes #19311

Clause-②: no

Why that reading: two .describe() strings and one TSDoc block. No key is added, removed or re-typed, no closed set gains a member, no export moves and no refinement changes. check:authorable-surface and check:api-surface are both green with no delta, and the wizard-step and group co-declaration refusals parse identically before and after. Grade: patch, measured below rather than pattern-matched.

The defect, re-derived on origin/main rather than taken on trust

FormSectionSchema declares two authorable booleans with no .describe() at all, between neighbours that have one:

packages/spec/src/ui/view.zod.ts:3315   collapsible: z.boolean().default(false),
packages/spec/src/ui/view.zod.ts:3316   collapsed:   z.boolean().default(false),

Lit control, same file, same instrument: view.zod.ts:1054 reads collapsed: z.boolean().default(false).describe('Collapse groups by default (presentation only)') — a different schema (group-by presentation). So a describe on a key of this name IS visible to the grep, and the zero at :3315–3316 is a reading, not a blind spot. Dark control: git grep -n "collapsedd" over the same file → 0 hits, exit 1.

Downstream of that silence, the generated page printed two empty Description cells (content/docs/references/ui/view.mdx:334-335, and again at :466-467 and :482-483, the three places that page projects this schema).

This is NOT the surface the first increment landed on. PR #19699 (merged fa29803417) corrected packages/spec/src/data/object.zod.ts:1220 — the ObjectFieldGroup pair, a different schema in a different file, which is why it merged as Part of. Both keys of this pair are described here, not just collapsed: describing one of a silent pair recreates the ambiguity one key over.

Probe — every sentence measured against the BUILT package

Built with pnpm --filter @objectstack/spec build, then probed through the module the exports map resolves (require.resolve('@objectstack/spec/ui')packages/spec/dist/ui/index.js, printed in the same run).

A. FormSectionSchema.safeParse, one section, all four combinations

authored collapsible out collapsed out
neither — CONTROL (lit): default arm must fire false false
collapsible: true true false
collapsible: false false false
collapsed: true false true
collapsed: false false false
both true true true
collapsed: true + collapsible: false false true
collapsed: false + collapsible: true true false
both false false false
collapsable: trueCONTROL (dark) REFUSED unrecognized_keys
collapsed: 'true'CONTROL (dark) REFUSED invalid_type@collapsed

Both lit and both dark controls answered as predicted, so the nine readings are measurements.

B. The normalizer question the dispatch asked — answered NO

There is no normalizer, no parse wrapper and no fold between these two keys. { collapsed: true } parses to { collapsible: false, collapsed: true }, verbatim, with both keys present in the output (.default(false)), and safeParseAsync returns the same. The section's only .transform is normalizeVisibleWhen, which touches visibleOn and nothing else.

⇒ That is the precision limit, and it is stated in the text rather than left implied: the implication collapsedcollapsible is a renderer rule applied from the declaration, never a parse-time rewrite. The describes say so explicitly, and say that the parsed collapsible must never be read as "a disclosure control renders". This is the exact opposite of the ObjectFieldGroup pair, where a real parse-time mapping folds the booleans onto the ADR-0085 collapse enum — the two surfaces share key names and share nothing else, so the describes name that difference.

C. The two refusals the describes claim

input wizard form beside group
collapsed: true REFUSED at sections.0.collapsed REFUSED at collapsed
collapsible: true REFUSED at sections.0.collapsible REFUSED at collapsible
collapsed: false ACCEPTED ACCEPTED
collapsible: false ACCEPTED ACCEPTED
neither — CONTROL (lit) ACCEPTED ACCEPTED
simple form + collapsed: trueCONTROL (lit) ACCEPTED (the refusal is wizard-only)
group + fieldsCONTROL (dark) REFUSED at group

⚠️ The first run of this block had its two lit controls come out REFUSED. That was a malformed fixture on my side (FormViewSchema is the form CONFIG and carries no name / label / objectName), not a reading — so those rows were discarded and the block re-run after the fixture was repaired. The table above is the repaired run. Recorded because the controls are the only reason the first, wrong version did not ship as a finding.

D. Reverse verification — the gate can see this change

After the describe edit and a spec rebuild, pnpm --filter @objectstack/spec check:generated exits 1 and names exactly one stale artifact — content/docs/references/** — while the other 14 stay green. Direction observed = turns red, as predicted. After gen:schema && gen:docs the same aggregate exits 0. That is what makes the final green a measurement rather than a silence.

Downstream consumer, read at the PINNED sha

Read at .objectui-sha = 87af769e9a3ee28ace099fdd653d3ebd79fe82e2 (not objectui's head, which is 0cf2d66); git merge-base --is-ancestor on the pin exits 0, which is self-proving.

  • packages/plugin-form/src/ObjectForm.tsx:1560 applies the ruling: Boolean(section.collapsible) || Boolean(section.collapsed), with a block comment that states it is read from the DECLARATION and never from live collapse state, and that letters B (refuse the combination) and C (a dev-only warning) were both refused. The describes follow that, and ⛔ neither adds a refinement nor asks for a lint rule.
  • packages/plugin-form/src/DrawerForm.tsx:609 and :677 still push collapsible: section.collapsible alone on both drawer arms. That file's own comment declares the gap deliberate and fenced, and says converging it is the collapsed / collapsible decision. So the contract this PR publishes is the thing that arm was waiting on — it is a sibling-repo residual, another seat's card, and nothing here touches it. Reported, not ridden along.
  • In this repo nothing consumes the raw pair: git grep for a .collapsible / .collapsed member access across packages/** returns only the ObjectFieldGroup mapping and test files; packages/lint/src has 0 hits for collapsible, with a positive control (form-section-group-unknown, 2 files) firing on the same command and scope.
  • All 22 first-party form producers under packages/spec/src/**/*.form.ts pair collapsible: true with collapsed: true, so zero in-repo producers exercise the trap. It is an author-facing trap, not a live in-repo defect — which is precisely why the remedy is declaration text.

Generated artifacts — the four-step sequence, run mechanically

content/docs/references/** is routed merge=os-regen, the class that merges with exit 0 and zero conflict markers while silently dropping one side.

  1. bash scripts/pm/os-regen-merge.sh — steps 1–3, exit 0. It merged origin/main (e37ea4d060), took main's side of the generated artifacts main moved, and committed the merge before any regeneration. ⛔ No rebase, ⛔ no force-push, ⛔ no git stash, ⛔ no hand merge of a routed path.
  2. gen:schema was run only after MERGE_HEAD was gone and the tree was clean, so the authorable-surface anchor could not roll back to the old fork point. packages/spec/authorable-surface.base.json is byte-identical to origin/main.
  3. Regenerated pnpm --filter @objectstack/spec build && gen:schema && gen:docs. Exactly one file moved, and by exactly the rows this one change derives: 6 rows in content/docs/references/ui/view.mdx — the pair, three times, because that page projects FormSectionSchema three times. git diff --name-only origin/main -- content/docs/references/ names that file and no other.
  4. Inspected the staged diff (git diff --cached), not the working-tree diff, before committing.

Survival assertion for the in-flight sibling, PR #19618

#19618 (open, draft, head 7cc0ca1b3d) touches four content/docs/references/** pages. It is unmerged, so what my regeneration could destroy is main's copy of those pages. Quoted-exact git grep -F, counts identical on my tree and origin/main:

needle path mine origin/main
the pre-#19618 tenancy type spelling carrying organizationField? api/metadata.mdx 1 1
same data/object.mdx 1 1
same system/migration.mdx 2 2
#19618's post-change tenancy spelling all four 0 0 (it has not landed)
STAMP-ONLY: column carrying the organization a row is ABOUT (its deletion target) data/object.mdx 2 2
CONTROL (lit) Multi-tenancy configuration for SaaS applications all four 1 / 1 / 2 fires
CONTROL (dark) a near-miss of the same spelling all four 0, exit 1 discriminates

All four of its reference pages are byte-identical to origin/main in my tree (git hash-object vs git rev-parse origin/main:PATH, four matching pairs). Every os-regen-routed path outside content/docs/references/ui/view.mdx differs from origin/main by zero files.

Also asserted, because the merge driver swallows implementation bodies and not only index entries: the previous increment's body survives — git grep -cF "true → 'collapsed' (collapsible, starts closed) on its own" reads 1 in packages/spec/src/data/object.zod.ts and 2 in content/docs/references/data/object.mdx, identical on my tree and origin/main, with a near-miss dark control at 0 / exit 1.

Changeset — measured, not pattern-matched

npm pack --dry-run --json in packages/spec (exit 0, 2031 files):

file verdict
src/ui/view.zod.tsthe edited file SHIPS
package.jsonpositive control SHIPS
src/data/object.zod.tspositive control SHIPS
src/ui/view.test.tsnegative control does NOT ship
scripts/build-docs.tsnegative control does NOT ship
tsconfig.jsonnegative control does NOT ship

Scanning the tarball's own file list for the new describe text: 42 shipped files carry it — 30 under dist/, 11 under json-schema/, 1 under src/. Negative control with a lit leg: the string are GENERATED — do not hand-edit them is present in packages/spec/scripts/lib/generated-output.ts and in 0 shipped files, because that file does not ship.

⇒ The bytes publish, so skip-changeset would be a false declaration. A patch changeset is in the diff.

Acceptance notes — found, ⛔ not fixed here

  • packages/spec/src/ui/view.zod.ts:3274 and :5951 describe the pair in prose and in a doc example without the dependency; neither is falsified by this change and neither is a trap as written (the :5951 example writes both keys). Noted, not filed.
  • The sections / groups rows on the generated page print a truncated inline type (… collapsible?: boolean; …) with no Description at all. That is the generator's type-column truncation, not this pair, and it is unchanged here.
  • packages/lint carries no rule on this pair (0 hits, positive control firing). Consistent with the 2026-09-18 ruling, which refused letter C — a dev-only warning — so this is a deliberate absence, ⛔ not a gap to fill.

Generated by Claude Code

`FormSectionSchema.collapsible` and `.collapsed` were two published,
authorable booleans with no `.describe()` at all, sitting between
neighbours that have one, so the generated reference page printed two
empty Description cells and the dependency between them reached nobody.

Both now carry contract text, plus one TSDoc block that states the pair
once. Every sentence is measured against the built package: parse does
NOT normalize the pair in either direction (`{ collapsed: true }` parses
to `{ collapsible: false, collapsed: true }`, and `safeParseAsync`
agrees), so the implication `collapsed` -> `collapsible` is a renderer
rule read from the declaration and has to be stated on the declaration
or it reaches no author.

Claude-Session: https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr
Co-authored-by: Claude <noreply@anthropic.com>
…geset

`gen:schema && gen:docs` after the describe edit. Exactly six rows move
in `content/docs/references/ui/view.mdx` — the collapse pair in the
three places that page projects `FormSectionSchema` — and nothing else
under `content/docs/references/**` differs from `origin/main`.

Claude-Session: https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation protocol:ui tooling labels Sep 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 1 documentable anchor(s).

1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/protocol/objectui/layout-dsl.mdx (via FormSectionSchema (symbol, a top-level const))

1 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v15.mdx (via FormSectionSchema (symbol, a top-level const))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • the SDK route bridge reached 60 of 215 client-bound route-ledger rows — the other 155 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 155: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 100 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 136 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json e37ea4d0602830b6b0f183b81689b321f127306fpackageMentionDocs.

Which tree this was computed on

This run read content/docs from 51c19ce993269aa0d5a41bf842abb3ea28c785ee — the merge of head 8ea5a49fe145f095658eefa3478a9afa5a26abdf into base e37ea4d0602830b6b0f183b81689b321f127306f, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 51c19ce993269aa0d5a41bf842abb3ea28c785ee && git checkout 51c19ce993269aa0d5a41bf842abb3ea28c785ee
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e37ea4d0602830b6b0f183b81689b321f127306f 8ea5a49fe145f095658eefa3478a9afa5a26abdf && git checkout -B drift-repro e37ea4d0602830b6b0f183b81689b321f127306f && git merge --no-ff 8ea5a49fe145f095658eefa3478a9afa5a26abdf

node scripts/docs-audit/affected-docs.mjs --json e37ea4d0602830b6b0f183b81689b321f127306f

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs e37ea4d0602830b6b0f183b81689b321f127306f → pass the list as
args.docs, on the commit named under Which tree this was computed on.

Copy link
Copy Markdown
Collaborator Author

Contract review

Served-tier: 124/124 CONTRACT_REVIEW_TIER (seat-measured, 2026-09-22T15:35Z)
Head-sha: 8ea5a49fe145f095658eefa3478a9afa5a26abdf

Rendered by an isolated at-tier review subagent.

① Derived judgments

Clause-②, path limb: HIT. The diff touches packages/spec/src/ui/view.zod.ts, so at-tier review is owed; this record is it. Declaration limb: Clause-②: no — judged CORRECT by measurement, ⛔ not by reading the diff. @objectstack/spec was built three times in isolated worktrees (merge-base e37ea4d060, origin/main 342808cf5e, head 8ea5a49fe1) and one probe of 38 parse rows was run through the package's exports map: FormSectionSchema 11 rows + 2 safeParseAsync, FormViewSchema 9, FormSectionSchema+group 7, layout-dsl constructs 9. Output byte-identical across all three builds — no accept-set movement, no parsed-value movement. Built json-schema/ trees (1538 files each): merge-base vs head differ in 11 files; with every description blanked, exactly 124 differing paths remain and all 124 are …collapsible.description (added) / …collapsed.description (added), 0 of any other kind. authorable-surface.base.json byte-identical to origin/main. ⇒ text-only. no stands.

Fixes #19311 is honest. The card's subject is FormSectionSchema at view.zod.ts:3315-3316, where at merge-base both keys carried no .describe(). The head describes bothcollapsible at :3346-3354, collapsed at :3355-3363 — plus one TSDoc block at :3315-3345. ⛔ Not confused with #19699 (fa29803417), which edited data/object.zod.ts:1220 and correctly landed as Part of. Both guards agree at head: Part-of PR must not also close its card and The card this PR closes must claim this branch, SUCCESS.

Every claim in the new describe text, verified at source:

  • «collapsed: true IMPLIES this key — an explicit collapsible: false beside it does NOT take the control away (ruled 2026-09-18)» — ruling located: objectui#9780 comment 5729750150, letter A, maintainer 「其他同意」, text: «collapsible: false with collapsed: true is the same contradiction and resolves the same way (collapsed wins, toggle present)». Implemented at the pinned .objectui-sha 87af769e: ObjectForm.tsx:1560 reads Boolean(section.collapsible) || Boolean(section.collapsed). TRUE.
  • «parse never rewrites the pair» — measured on the head build: {collapsed:true}{collapsible:false, collapsed:true}; with collapsible:false beside it, the same. safeParseAsync agrees. Lit control: neither key → false,false, the default arm fires. Dark controls: collapsable:trueunrecognized_keys; collapsed:'true'invalid_type. TRUE.
  • «The renderer resolves that from the DECLARATION» — TRUE of the ruled contract and of ObjectForm.tsx:1560 at the pin. ⚠️ Not yet true on the drawer arm — see ③.
  • «Only true is refused on a wizard step and beside group; false is accepted in both» — the refusals exist and were exercised on the built head. Wizard: refinement at view.zod.ts:4218-4242; type:'wizard'+collapsed:truecustom@sections.0.collapsed, collapsible:truecustom@sections.0.collapsible, either false or neither → ACCEPTED. Lit controls simple+collapsed:true and tabbed+collapsible:true → ACCEPTED, proving it is wizard-only. Beside group: view.zod.ts:3490 trueOnlyDerivedKeys consumed at section-group-reference.ts:161-164; group+collapsed:truecustom@collapsed, both false → ACCEPTED, group alone → ACCEPTED. Class control group+label → refused (derivedKeys refuse ANY value, so the true-only asymmetry is real). Dark control group+fields → refused at group. TRUE.
  • TSDoc «opposite of the fieldGroups pair on ObjectSchema, which a parse-time mapping folds onto the collapse enum» — measured: fieldGroups:[{…collapsed:true}]collapse:'collapsed'; +collapsible:false'collapsed'; collapsible:true alone → 'expanded'; neither → 'none'. Mapping site object.zod.ts:2831. TRUE.

⭐ The drift-check question, settled by PARSING and ⛔ not by name. layout-dsl.mdx:196 («There is no wizard template») and the describe's «wizard step» are DIFFERENT constructs, measured:

  • PageSchema + {template:'wizard', steps:[…]}REFUSED unrecognized_keys at steps; FormViewSchema + the same literal → REFUSED at template, steps.
  • FormViewSchema + {type:'wizard', sections:[…]}ACCEPTED.

⇒ The describe's refusal lives on the accepted construct; the page's tombstone is on the refused one. Likewise :428 («no field_group, no section-level layout:»): {type:'field_group'} → REFUSED at type, layout:[…] → REFUSED at layout, {group:'g'} → ACCEPTED — different constructs again. The page's :349-358 literal parses ACCEPTED and :835-836 is consistent. The page is silent on the implication rule — a gap, ⛔ not a falsehood, and nothing on it is falsified by this PR. content/docs/releases/v15.mdx:245 remains true; ⛔ no card owed there.

② Semver level

patch on @objectstack/spec — correct, and the changeset is present. Measured in the reviewer's own worktree at head: real build (exit 0, DTS included), then npm pack --dry-run --json → 2031 files.

  • Membership: src/ui/view.zod.ts SHIPS. Positives: package.json, src/data/object.zod.ts SHIP. Negatives: src/ui/view.test.ts, scripts/build-docs.ts, scripts/lib/schema-section.ts, tsconfig.json do NOT ship.
  • Reach, counted over the tarball's own list: each new describe in 42 shipped files (30 dist, 11 json-schema, 1 src). CLASS controldocs(spec): state what fieldGroups[].collapsed maps to on its own #19699's describe, known to publish — 32 shipped. NEGATIVE with a lit leg — a generator-only phrase — 0 shipped against 1 in the package dir. DARK near-miss spelling — 0/0.

skip-changeset would be a false declaration; patch is the right level.

③ Boundary flags

  • The regenerated content/docs/references/ui/view.mdx is generator output, ⛔ not a hand edit: the AUTO-GENERATED banner is present; the diff moves exactly 6 rows (the pair × the page's 3 projections of FormSectionSchema), the three projections are md5-identical, and each Description cell is byte-equal to the built package's description. Negative control: the merge-base cells are empty.
  • Manual floor: not triggered. .claude/**, skills/**, docs/adr/**, content/docs/releases/** untouched; Governed Surface Queue Guard SUCCESS.
  • CI at head, carried from check-runs and ⛔ not re-run: 35 runs — 33 success, 2 skipped (Console Pin Gate path-gated, Packed-tarball smoke opt-in), 0 failure.
  • ⚠️ Sibling-repo residual, ⛔ not this PR's: objectui DrawerForm.tsx:609/:677 pushes collapsible alone and does not apply the ruling, with a comment declaring the gap deliberately fenced on the collapsed/collapsible decision — which this PR publishes. The seat has measured it on objectui's current main (0cf2d6644bdb, newer than the pin), so it is ⛔ not an artifact of pin lag, and a semantic search found no open card. Owed there with a Blocked-by: link; the seat files it on acceptance.
  • Not measured: renderer behaviour was verified by reading objectui source at the pin, ⛔ not by executing it.

Implemented-by: claude/issue-19311-form-section-collapse-describes
Reviewed-by: session_013RDBh5DqXd2xnLwvHLgLFr

VERDICT: PASS


Tier control — measured by the seat

  • 124 assistant requests, 124 stamped claude-fable-5-1; 159/159 counting every model field.
  • Dark control: 0 — filtering for anything other than that value returns empty.
  • The four fallback/overload hits are tool-schema prose. ⛔ None is a notice.
  • CONTRACT_REVIEW_TIER re-read at origin/main:scripts/pm/dispatch-gates.mjs = claude-fable-5-1.

Two corrections the reviewer made mid-run, recorded rather than smoothed

  1. Its first CLASS pack control mis-spelled the needle through shell quoting and read 0. Re-run with the needle copied from source, it reads 32. ⭐ A class control that reads zero is indistinguishable from a real absence — the only reason this did not ship as a finding is that the control was expected to fire.
  2. Its first PageSchema fixture failed on its own required keys before yielding a reading. Fixture faults, ⛔ not readings, and discarded.

Housekeeping

The reviewer's git worktree prune also dropped the registration of /home/user/objectstack-19311-view. The seat verified: that directory no longer exists and the worktree list is clean. Prune cannot delete a directory, so the dev had already removed its own — ⛔ no work was lost.


Generated by Claude Code

@os-support-ai
os-support-ai marked this pull request as ready for review September 22, 2026 15:36
@os-support-ai
os-support-ai added this pull request to the merge queue Sep 22, 2026
Merged via the queue into main with commit b01bdbc Sep 22, 2026
37 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-19311-form-section-collapse-describes branch September 22, 2026 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:ui size/s tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

finding(spec): the sections[].collapsed describe owes an 「implies collapsible」 clause

2 participants